package com.aifast.common.fieldEncrypt;

import cn.hutool.core.util.ObjectUtil;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Properties;
import java.util.Set;

/**
 * @Author fujian
 * @since 2022/9/12 11:58
 */
@Component
@Intercepts({
        @Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})
})
public class DecryptInterceptor implements Interceptor {
    @Resource
    private AiEncryptor aiEncryptor;

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object proceed = invocation.proceed();
        if (proceed instanceof ArrayList) {
            ArrayList list = (ArrayList) proceed;
            if (list.isEmpty()) {
                return proceed;
            }
            Object first = list.get(0);
            if (ObjectUtil.isNull(first)) {
                return proceed;
            }
            Set<Field> fields = FieldsProvider.get(first.getClass());
            if (ObjectUtil.isNull(fields) || fields.isEmpty()) {
                return proceed;
            }
            list.forEach(i -> {
                set(fields, i);
            });
        } else {
            if (ObjectUtil.isNotNull(proceed)) {
                set(FieldsProvider.get(proceed.getClass()), proceed);
            }
        }
        return proceed;
    }

    private void set(Set<Field> fields, Object result) {
        if (ObjectUtil.isNull(fields) || fields.size() == 0) {
            return;
        }
        fields.forEach(i -> {
            FieldEncrypt annotation = i.getAnnotation(FieldEncrypt.class);
            if (ObjectUtil.isNull(annotation)) {
                return;
            }
            try {
                i.setAccessible(true);
                Object rawData = i.get(result);
                if (ObjectUtil.isNull(rawData)|| ObjectUtil.isEmpty(rawData)) {
                    return;
                }
                String decrypt = aiEncryptor.decrypt(rawData, annotation.type(), annotation.key());
                i.set(result, decrypt);

            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        });

    }

    @Override
    public Object plugin(Object target) {
        return Interceptor.super.plugin(target);
    }

    @Override
    public void setProperties(Properties properties) {
        Interceptor.super.setProperties(properties);
    }
}
